
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { MapType } from "@/type";
import { RESPONSE_CODE } from "@/enums/code";
import { getPageWhere, getPageData, } from '@/utils/page'
import { User } from './user.model';
import { DeptService } from '../dept/dept.service';
import { RoleService } from '../role/role.service';
import { Op } from 'sequelize'
import { userDefaultMd5Password } from '@/config/user'
import { AddAddUserDto, UpdateAddUserDto, QueryUserPageDto } from './users.dto'

@Injectable()
export class UsersService {
  constructor(
    @InjectModel(User)
    private userModel: typeof User,

    private deptService: DeptService,
    private roleService: RoleService,
  ) { }

  /**
  * 获取所有用户
  * @method get
  */
  async getUserAll() {
    const list = await User.findAll();
    return {
      code: RESPONSE_CODE.SUCCESS,
      data: list,
      msg: null,
    }
  }

  /**
   * 获取用户信息
   * @method get
   * @param userId 
   * @returns 
   */
  async getUserInfo(userId) {
    const user = await this.userModel.findByPk(userId, {
      attributes: {
        exclude: ["password", "refresh_token", "token"],
      },
    });
    const sysUser = {
      ...user,
      uniPushInfo:
        '{"androidClientId":"","isoClientId":"586b055a004fa1805c8b40b99a8c59f432"}',
    };
    const mockData = {
      sysUser,
      permissions: [
        "792355637819478016:POST-ALLOCATION",
        "1001:TABLE-ADD",
        "1002:ADD-USER",
        "1004:ADD-POST",
        "792355637819478016:POST-EDIT",
        "1001:EXPORT",
        "1002:EDIT-USER",
        "1002:RESET-PADDWORD",
        "1001:TABLE-EDIT",
        "1004:TO-CHANNEL-POST",
        "1003:ROLE-DELETE",
        "1004:TABLE-EDIT-POST",
        "1002:EXPORT-USER",
        "1002:DELETE-USER",
        "1003:APP-MENU-ROLE-AUTH",
        "1003:CHECKOUT-ROLE",
        "792355637819478016:DELETE-MUlTIPLE",
        "1001:TABLE-DELETE",
        "1003:EDIT-ROLE",
        "1003:MENU-ROLE-AUTH",
        "714847840469711036:ADD-DEPT",
        "714847840469711036:TABLE-ADD",
        "1002:TO-CHANNEL-USER",
        "792355637819478016:POST-WATCH-INFO",
        "1003:EXPORT-ROLE",
        "1001:TO-CHANNEL",
        "792355637819478016:POST-DELETE",
        "1004:TABLE-DELETE-POST",
        "792355641648877602:CurveDefaultValue",
        "1003:DATA-ROLE-AUTH",
        "1004:EXPORT-POST",
        "1003:ADD-ROLE",
      ],
      roles: ["1", "4595", "4825"],
      deptPermList: null,
      sysDept: null,
    }
    return {
      code: RESPONSE_CODE.SUCCESS,
      data: mockData,
      msg: null
    }

  }

  /**
   * 新增用户
   * @method post
   * @param addAddUserDto
   */
  async addUser(addAddUserDto: AddAddUserDto) {
    const [created] = await this.userModel.findOrCreate({
      where: { name: addAddUserDto.name },
      defaults: {
        ...addAddUserDto,
        password: userDefaultMd5Password,
        role: addAddUserDto.role.length ? addAddUserDto.role.join(",") : "",
      }
    })
    return {
      code: created ? RESPONSE_CODE.SUCCESS : RESPONSE_CODE.ERROR,
      data: [],
      msg: created ? "" : "用户已存在",
    }
  }

  /**
   * 更新用户
   * @method post
   * @param updateAddUserDto
   */
  async updateUser(updateAddUserDto: UpdateAddUserDto) {
    const res = await this.userModel.update(
      {
        ...updateAddUserDto,
        role: updateAddUserDto.role.length ? updateAddUserDto.role.join(",") : "",

      },
      { where: { userId: updateAddUserDto.userId } })
    return {
      code: res ? RESPONSE_CODE.SUCCESS : RESPONSE_CODE.ERROR,
      data: [],
      msg: res ? "" : "用户不存在",
    }
  }

  /**
   * 批量重置密码
   * @method post
   * @param ids
   */
  async resetUser(ids: number[]) {
    await this.userModel.update(
      {
        password: userDefaultMd5Password,
      },
      {
        where: {
          userId: {
            [Op.in]: ids,
          },
        },
      }
    );
    return {
      code: RESPONSE_CODE.SUCCESS,
      data: [],
      msg: "",
    }
  }

  /**
   * 删除用户
   * @method post
   * @param userId
   */
  async delUser(userId: Number) {
    const user = await this.userModel.findOne({
      where: { userId, },
    });
    if (user) {
      await user.destroy();
    }
    return {
      code: RESPONSE_CODE.SUCCESS,
      data: [],
      msg: null
    }
  }

  /**
   * 获取用户信息
   * @method get
   * @param userId
   */
  async getUserById(userId: Number) {
    const user = await this.userModel.findOne({
      where: { userId },
      attributes: {
        exclude: ["password", "refresh_token"],
      },
    });
    if (!user) {
      return {
        code: RESPONSE_CODE.ERROR,
        data: user,
        msg: "用户不存在"
      }
    }

    // 再查role
    // 用户角色ID
    const allRoleIds = Array.from(
      new Set(user.dataValues.role?.split(",")?.map((id: string) => Number(id)))
    );
    // 查询所有相关的角色
    const roles = await this.roleService.publicMethods("findAll", { where: { roleId: allRoleIds } })
    const roleMap: MapType = {};
    roles.forEach((role) => {
      roleMap[role.dataValues.roleId] = role.dataValues;
    });
    // 给每个用户加上roleList
    const userWithRoles = () => {
      const roleIds: number[] = user.dataValues.role
        ? user.dataValues.role
          ?.split(",")
          .filter(Boolean)
          .map((id: string) => Number(id))
        : [];

      return {
        ...user.dataValues,
        roleList: roleIds.map((id) => roleMap[id]).filter(Boolean),
      };
    };

    // 再查dept
    // 收集用户部门id
    const allDeptIds = Array.from(
      new Set(
        user.dataValues.dept
          ?.split(",")
          .filter(Boolean)
          .map((id: string) => Number(id))
      )
    );

    // 查询所有相关的部门
    const depts = await this.deptService.publicMethods("findAll", { where: { id: allDeptIds } });
    const deptMap: MapType = {};
    depts.forEach((dept) => {
      deptMap[dept.dataValues.id] = dept.dataValues;
    });
    // 给每个用户加上deptList
    const userWithDepts = () => {
      const dept = user.dataValues.dept ?? null;
      return {
        ...userWithRoles(),
        deptList: dept ? [deptMap[dept]] : [],
        dept: undefined,
      };
    };

    return {
      code: RESPONSE_CODE.SUCCESS,
      data: userWithDepts(),
      msg: null
    }
  }

  /**
* 获取用户列表
* @method get
* @param userId 
* @returns 
*/
  async getUserPage(queryUserPageDto: QueryUserPageDto) {
    const { current, size, name, role, phone, email } = queryUserPageDto

    const query: any = {};
    if (name) {
      query["name"] = {
        [Op.like]: `%${name}%`,
      };
      query["username"] = {
        [Op.like]: `%${name}%`,
      };
    }
    if (role) {
      query["role"] = role;
    }
    if (phone) {
      query["phone"] = {
        [Op.like]: `%${phone}%`,
      };
    }
    if (email) {
      query["email"] = {
        [Op.like]: `%${email}%`,
      };
    }

    const { count, rows: users } = await this.userModel.findAndCountAll({
      where: query,
      attributes: {
        exclude: ["password", "dept"],
      },
      ...getPageWhere(current, size),
    });

    // 再查role
    // 收集所有用户角色ID
    const allRoleIds = Array.from(
      new Set(
        users
          .map((u) => u.dataValues.role)
          .filter(Boolean)
          .flatMap((str) => str.split(",").map((id: string) => Number(id)))
      )
    );
    // 查询所有相关的角色
    const roles = await this.roleService.publicMethods('findAll', { where: { roleId: allRoleIds } });
    const roleMap: MapType = {};
    roles.forEach((role) => {
      roleMap[role.dataValues.roleId] = role.dataValues;
    });
    // 给每个用户加上roleList
    const userWithRoles = users.map((user) => {
      const roleIds: number[] = user.dataValues.role
        ? user.dataValues.role.split(",").map((id: string) => Number(id))
        : [];
      return {
        ...user.dataValues,
        roleList: roleIds.map((id) => roleMap[id]).filter(Boolean),
      };
    });

    // 再查dept
    // 收集所有用户部门id
    const allDeptIds = Array.from(
      new Set(users.map((u) => Number(u.dataValues.deptId)).filter(Boolean))
    );


    // 查询所有相关的部门
    const depts = await this.deptService.publicMethods('findAll', { where: { id: allDeptIds } });
    const deptMap: MapType = {};
    depts.forEach((dept) => {
      deptMap[dept.dataValues.id] = dept.dataValues;
    });
    // 给每个用户加上deptList
    const userWithDepts = userWithRoles.map((user) => {
      const dept = user.deptId ?? null;
      return {
        ...user,
        deptName: deptMap[dept].name,
      };
    });


    return {
      code: RESPONSE_CODE.SUCCESS,
      data: getPageData(current, size, count, userWithDepts),
      msg: null
    }
  }

  /**
   * 获取用户列表
   * @method get
   * @param userId 
   * @returns 
   */
  async getUserPageV2(queryUserPageDto: QueryUserPageDto) {
    const { current, size, name, role, phone, email } = queryUserPageDto

    const query: any = {};
    if (name) {
      query["name"] = {
        [Op.like]: `%${name}%`,
      };
      query["username"] = {
        [Op.like]: `%${name}%`,
      };
    }
    if (role) {
      query["role"] = role;
    }
    if (phone) {
      query["phone"] = {
        [Op.like]: `%${phone}%`,
      };
    }
    if (email) {
      query["email"] = {
        [Op.like]: `%${email}%`,
      };
    }

    const { count, rows: users } = await this.userModel.findAndCountAll({
      where: query,
      attributes: {
        exclude: ["password", "dept"],
      },
      ...getPageWhere(current, size),
    });

    // 再查role
    // 收集所有用户角色ID
    const allRoleIds = Array.from(
      new Set(
        users
          .map((u) => u.dataValues.role)
          .filter(Boolean)
          .flatMap((str) => str.split(",").map((id: string) => Number(id)))
      )
    );
    // 查询所有相关的角色
    const roles = await this.roleService.publicMethods('findAll', { where: { roleId: allRoleIds } });

    const roleMap: MapType = {};
    roles.forEach((role) => {
      roleMap[role.dataValues.roleId] = role.dataValues;
    });
    // 给每个用户加上roleList
    const userWithRoles = users.map((user) => {
      const roleIds: number[] = user.dataValues.role
        ? user.dataValues.role.split(",").map((id: string) => Number(id))
        : [];
      return {
        ...user.dataValues,
        roleList: roleIds.map((id) => roleMap[id]).filter(Boolean),
      };
    });

    // 再查dept
    // 收集所有用户部门id
    const allDeptIds = Array.from(
      new Set(users.map((u) => Number(u.dataValues.deptId)).filter(Boolean))
    );


    // 查询所有相关的部门
    const depts = await this.deptService.publicMethods('findAll', { where: { id: allDeptIds } });
    const deptMap: MapType = {};
    depts.forEach((dept) => {
      deptMap[dept.dataValues.id] = dept.dataValues;
    });
    // 给每个用户加上deptList
    const userWithDepts = userWithRoles.map((user) => {
      const dept = user.deptId ?? null;
      return {
        ...user,
        deptName: deptMap[dept].name,
      };
    });


    return {
      code: RESPONSE_CODE.SUCCESS,
      data: getPageData(current, size, count, userWithDepts),
      msg: null
    }
  }

  /**
  * 获取导出用户标题
  * @param 
  */
  async getCustomExportTitles() {
    return {
      code: RESPONSE_CODE.SUCCESS,
      data: [
        "用户编号",
        "用户名",
        "姓名",
        "昵称",
        "手机号",
        "工号",
        "邮箱",
        "部门名称",
        "部门编码",
        "角色",
        "锁定标记,0:正常,9:已锁定",
        "创建时间",
      ],
      msg: null,
    };
  }

  /**
 * 获取导出用户标题
 * @param 
 */
  async getUserOptions() {
    const data = await this.userModel.findAll({
      attributes: ["userId", "name", "username", "userCode"],
    });
    return {
      code: RESPONSE_CODE.SUCCESS,
      data,
      msg: null,
    };
  }

  async getUserByUsername(username, password) {
    return this.userModel.findOne({ where: { userCode: username, password } });
  }

  /**
   * 获取用户信息
   * @param userId number
   */
  async findUserInfo(userId: number): Promise<User | null> {
    const user = await this.userModel.findOne({
      where: {
        userId,
      }
    });
    return user?.dataValues || null;
  }


  /**
   * 通用方法
   * @param methods 方法
   * @param query query 条件
   * @returns 
   */
  async publicMethods(methods: string, query: any) {
    return await this.userModel[methods]({ ...query });
  }
}



